package com.xxrl.shop.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xxrl.shop.common.entity.JsonResult;
import com.xxrl.shop.common.entity.ResultCode;
import com.xxrl.shop.common.utils.PageTool;
import com.xxrl.shop.common.utils.ResultTool;
import com.xxrl.shop.common.utils.StringUtils;
import com.xxrl.shop.config.log.ControllerLog;
import com.xxrl.shop.domain.*;
import com.xxrl.shop.service.MerchantService;
import com.xxrl.shop.service.ProductIndexService;
import com.xxrl.shop.service.ProductService;
import com.xxrl.shop.service.ProductTypeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author mis
 */
@Api(tags = {"product"})
@RequestMapping("/product")
@RestController
public class ProductController {

    private final ProductService productService;
    private final MerchantService merchantService;
    private final ProductIndexService productIndexService;
    private final ProductTypeService productTypeService;

    public ProductController(ProductService productService, MerchantService merchantService, ProductTypeService productTypeService, ProductIndexService productIndexService) {
        this.productService = productService;
        this.merchantService = merchantService;
        this.productTypeService = productTypeService;
        this.productIndexService = productIndexService;
    }

    @ApiOperation(value = "Homepage product list, hot list and recommend list.", response = Product.class, responseContainer = "List")
    @GetMapping("home")
    @ControllerLog
    public JsonResult<String> homeList(Long userId) {
        JSONObject json = new JSONObject();
        json.put("home_hot",productService.getHostProductList());
        json.put("home_floors",productService.getHomePage(userId));
        return ResultTool.success(json.toString());
    }

    @ApiOperation(value = "Get type list.", response = ProductType.class, responseContainer = "List")
    @GetMapping("type/list")
    @ControllerLog
    public JsonResult<String> typeList() {
        List<ProductType> list = productTypeService.getAllTypes();
        return ResultTool.success(JSON.toJSON(list).toString());
    }

    @ApiOperation(value = "Add a product type", response = ProductType.class, responseContainer = "JsonResult")
    @PostMapping("type/add")
    @ControllerLog
    public JsonResult<String> addType(String type) {
        ProductType newType = productTypeService.createType(type);
        return ResultTool.success(JSON.toJSON(newType).toString());
    }

    @ApiOperation(value = "Remove a product type", response = String.class, responseContainer = "JsonResult")
    @PostMapping("type/remove")
    @ControllerLog
    public JsonResult<String> removeType(String id) {
        productTypeService.deleteType(id);
        return ResultTool.success();
    }

    /**
     * 全部商品的加载请求
     *
     * @param page          第几页
     * @param size          页的大小， 现为默认值15
     * @param sortDirection 排序方向
     * @param priceGt       价格大于
     * @param priceLte      价格小于等于
     * @return Json结果
     */
    @ApiOperation(value = "Get all product list by page request with sort and price filter.", response = Product.class, responseContainer = "List")
    @GetMapping("loadList")
    @ControllerLog
    public JsonResult<String> loadList(@RequestParam(defaultValue = "0", name = "page") Integer page,
                                       @RequestParam(defaultValue = "15", name = "size") Integer size,
                                       @RequestParam(defaultValue = "", name = "sort") String sortDirection,
                                       @ApiParam(value = "price grater filter", example = "0") @RequestParam(defaultValue = "", name = "priceGt") Integer priceGt,
                                       @ApiParam(value = "price lower filter", example = "0") @RequestParam(defaultValue = "", name = "priceLte") Integer priceLte) {
        Page<Product> products;
        if (priceGt != null) {
            priceLte = priceLte != null ? priceLte : Integer.MAX_VALUE;
        }
        if (priceLte != null) {
            priceGt = priceGt != null ? priceGt : 0;
        }
        PageRequest pageRequest;
        if (StringUtils.isEmpty(sortDirection)) {
            pageRequest = PageRequest.of(page, size);
        } else if ("desc".equals(sortDirection)) {
            pageRequest = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC,"prices"));
        } else if("asc".equals(sortDirection)) {
            pageRequest = PageRequest.of(page, size, Sort.by(Sort.Direction.ASC,"prices"));
        } else {
            return ResultTool.fail(ResultCode.PARAM_NOT_VALID);
        }
        if (priceGt!=null) {
            products = productService.findAllPricesBetween(pageRequest,priceGt,priceLte);
        } else{
            products = productService.findAll(pageRequest);
        }
        List<Product> list = products.getContent();
        JSONObject json = new JSONObject();
        json.put("finish",list.size()!=size);
        json.put("items",list);
        return ResultTool.success(json.toString());
    }

    @ApiOperation(value = "Search products by keyword.", response = Product.class, responseContainer = "List")
    @GetMapping("search")
    @ControllerLog
    public JsonResult<String> search(@RequestParam(defaultValue = "0", name = "page")Integer page,
                                     @RequestParam(defaultValue = "12", name = "size")Integer size,
                                     @RequestParam(name = "name")String productName) {
        List<ProductIndex> list = productIndexService.queryListByName(productName, PageRequest.of(page, size)).getContent();
        JSONObject json = new JSONObject();
        json.put("finish",list.size()!=size);
        json.put("items",productService.productIndexToProductList(list));
        return ResultTool.success(json.toString());
    }

    /**
     * 商家获得自己商品的请求
     * @param page 第几页
     * @param size 页的大小
     * @param userId 用户id
     * @return Json结果
     */
    @GetMapping("merchantList")
    @ControllerLog
    public JsonResult<String> merchantList(@RequestParam(defaultValue = "0",name = "page")Integer page,
                                           @RequestParam(defaultValue = "10", name = "size")Integer size,
                                           @RequestParam(name = "userId")Long userId) {
        Page<Product> products = productService.findAllByUser(userId, PageRequest.of(page, size));
        return ResultTool.success(PageTool.pageToJson(products));
    }

    /**
     * 管理员查看所有商品的请求
     * @param page 页号
     * @param size 页的大小
     * @return Json结果
     */
    @GetMapping("list")
    @ControllerLog
    public JsonResult<String> list(@RequestParam(defaultValue = "0", name = "page")Integer page,
                                   @RequestParam(defaultValue = "10", name = "size")Integer size) {
        Page<Product> products = productService.findAll(PageRequest.of(page, size));
        return ResultTool.success(PageTool.pageToJson(products));
    }

    /**
     * 查询一个商品的详细信息
     * @param productId 商品id
     * @return Json结果
     */
    @GetMapping("detail")
    @ControllerLog
    public JsonResult<String> detail(Long productId) {
        Product product = productService.getProductById(productId);
        return ResultTool.success(JSON.toJSON(product).toString());
    }

    @GetMapping("recommend")
    @ControllerLog
    public JsonResult<String> recommend(Long productId) {
        List<Product> list = productService.recommendForProduct(productId);
        return ResultTool.success(JSON.toJSON(list).toString());
    }

    @PostMapping("add")
    @ControllerLog
    public JsonResult<String> add(Long userId, Product product) {
        Merchant user = merchantService.getMerchantByUser(new User(userId));
        if (user == null) {
            return ResultTool.fail(ResultCode.NO_PERMISSION);
        }
        productTypeService.ensureExist(product.getMainType());
        productTypeService.ensureExist(product.getSubType());
        product.setSellCount(0);
        product.setViewCount(0);
        productService.addProductByMerchant(user, product);
        productIndexService.insert(new ProductIndex(product.getName(), product.getKeywords(), product.getId()));
        return ResultTool.success("OK");
    }

    @PostMapping("edit")
    @ControllerLog
    public JsonResult<String> edit(Product product) {
        productService.saveProduct(product);
        productTypeService.ensureExist(product.getMainType());
        productTypeService.ensureExist(product.getSubType());
        productIndexService.insert(new ProductIndex(product.getName(), product.getKeywords(), product.getId()));
        return ResultTool.success("OK");
    }

    @PostMapping("delete")
    @ControllerLog
    public JsonResult<String> delete(@RequestParam(name = "id") Long productId) {
        productIndexService.deleteById(productId);
        productService.removeProduct(productId);
        return ResultTool.success("OK");
    }

}
